#ifndef GGL_H
#define GGL_H

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <list>
#include <sstream>
#include "GGLGlob.h"

typedef struct {
    int x;
    int y;
    int w;
    int h;
} AABB;

typedef struct {
    int x;
    int y;
} GGVec;

enum GGOrientation {
    Horizontal,
    Vertical
};

/* Sprite */

class GGLIB_EXPORT GGSprite {
public:
    GGSprite(std::string f, int i, int j);
    int getHeight();
    int getWidth();
    int getCurrentImage();
    float x();
    float y();
    sf::Sprite *getRawSprite();

    void move(float x, float y);
    void posAdd(float x, float y);
    void setImageCount(int ic);
    void setFPS(int f);
    void setCurrentImage(int ci);
    void enableDebug();

    void tick();
    void draw(sf::RenderWindow *w);

private:
    sf::Texture tex;
    sf::Sprite spr;

    float fps;
    int imgCount;

    int tickCounter;
    int width;
    short cFrame;
};

/* Lib */

namespace GG {
    void GGLIB_EXPORT initLib();
    int GGLIB_EXPORT random(int min, int max);
    float GGLIB_EXPORT frandom(int min, int max);
    std::string GGLIB_EXPORT intToStr(int i);
    void GGLIB_EXPORT repeatSprite(GGSprite *spr, sf::RenderWindow *win, int times);
}

/* Background */

class GGLIB_EXPORT GGBackground {
public:
    GGBackground(int ww = 640, int wh = 480, bool col = true);
    void setType(bool t);
    void setColor(sf::Color col);
    void setImage(std::string str);
    void draw(sf::RenderWindow *win);

private:
    bool isAColor;
    sf::RectangleShape bg;
    sf::Texture tex;
    sf::Sprite spr;

    int divX;
    int divY;
    int winW;
    int winH;
};

/* Object */

class GGLIB_EXPORT GGObject {
public:
    virtual void event(sf::Event e);
    virtual void tick();
    virtual void draw(sf::RenderWindow *w);
    virtual void move(int x, int y);
    GGSprite *getSprite();
    void setObjectId(int id);
    int getObjectId();
    int getObjectType();
    int getParent();
    bool destroyed();

    /* Physics */
    AABB getAABB();
    bool isCollidingWidth(AABB t);
    void setSolid(bool s);
    bool getSolid();
    void setDirection(bool top, bool bottom, bool left, bool right, bool topleft, bool topright, bool bottomleft, bool bottomright);
    void moveTick();
    void bounce();
    void bounce(GGOrientation o);
    bool isOutsideRoom();
    void readjustPosition(AABB t);
    void readjustSpeed();

    void stop();
    void unstop();
    bool getStopped();

    void setFollowTarget(bool f);
    void setTarget(sf::Vector2f v);
    bool isFollowingTarget();
    sf::Vector2f getTarget();

    void setSpeed(int s);
    void setAngle(int a);
    void setFreeMove(bool fm);
    int getSpeed();
    int getAngle();
    bool getFreeMove();

    void setXSpeed(float xs);
    void setYSpeed(float ys);
    float getXSpeed();
    float getYSpeed();

protected:
    GGSprite *spr;
    int objId;
    int objType;
    int parent;

    int angle;
    int speed;
    int dspeed;

    bool stopped;
    bool freeMove;

    bool followTarget;
    sf::Vector2f vec;

    int winW;
    int winH;

    float speedX;
    float speedY;

    bool solid;
    GGOrientation bo;
    bool alive;
};

/* Sound */

class GGLIB_EXPORT GGSound {
public:
    GGSound(std::string uri, bool rep, int vol, bool isSound);
    void play();
    void pause();
    void stop();
    bool isPlaying();

    sf::Sound *getSound();
    sf::Music *getMusic();
    bool getType();

private:
    sf::SoundBuffer *sndBuff;
    sf::Sound *snd;
    sf::Music *mus;
    bool type;
};

/* Timer */

class GGLIB_EXPORT GGTimer {
public:
    GGTimer(int ms = 0);
    void start();
    void stop();
    void pause();

    void tick();

    bool isOn();

    bool isEnded();
    int getTime();
    void setInterval(int ms);

private:
    int ticks;
    int interval;
    bool stopped;
};

#endif // GGL_H
